using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

namespace Halloween_Game
{
    /// <summary>
    /// Scene object is a container object which makes sure to update
    /// the objects according to the given input and the objects interaction.
    /// Also, it checks for collision detections and makes the according changes.
    /// </summary>
    public class Scene
    {
        /// <summary>
        /// This four int variables are used to calculate how many milliseconds have to pass
        /// before we draw a picture
        /// </summary>
        int lastReading;
        int totalTime;
        int temp;
        int currDiffenrence;
        int animCounter;
        int frames;
        Vector2 velocity;  //Velocity of the player
        
        //This is the camera which checks for the current position being beyond the viewport bounds
        Simple_Camera camera;

       //We need a sprite batch to draw the objects
        SpriteBatch batch;

        //the graphics device
        GraphicsDeviceManager graphics;

        //This integer array holds the dimensions of our viewing port
        private int[] dimension;

        public int[] Dimension
        {
            get { return dimension; }
            set { dimension = value; }
        }

        //This background object will draw our background
        private Background background;

        public Background MyBackground
        {
            get { return background; }
            set { background = value; }
        }
	
        //This is the data representing the sprite
        private Texture2D spriteTexture;

        public Texture2D SpriteTexture
        {
            get { return spriteTexture; }
            set { spriteTexture = value; }
        }

        private Vector2 textureOffset;

        public Vector2 TextureOffset
        {
            get { return textureOffset; }
            set { textureOffset = value; }
        }
	

        //Teh velocity of the moving sprite
        private Vector2 spritePos;

        public Vector2 SpritePosition
        {
            get { return spritePos; }
            set { spritePos = value; }
        }


        /// <summary>
        /// Scene object needs to be created with the graphics device and content manager
        /// of the calling game
        /// </summary>
        public Scene( GraphicsDeviceManager deviceM, int[] dimension )
        {
            Vector2 dim = new Vector2(0, 0);
            this.graphics = deviceM;
            this.Dimension = dimension;
            dim.X = this.Dimension[0];
            dim.Y = this.Dimension[1];
            this.camera = new Simple_Camera( dim );
            this.frames = 3;
        }

        //Loads all the graphics content for all the game objects
        //interacting in "this" game
        public void LoadGraphicsContent( ContentManager manager )
        {
            LoadResources(manager);
        }


        private void LoadResources( ContentManager manager )
        {

            //Set the string of names for the backgrounds
            string[] backNames = { "Background1", "Background2", "Background3", "Background4", "Background5" };

            //Create the background object with and give it the background names and the dimensions of the viewport
            this.background = new Background( backNames, this.dimension );

            //Calls the content manager given the content of "this" game
            this.background.LoadGraphicsContent( manager );

            this.SpritePosition = new Vector2(0, 0);


            //This is the velocity of the moving sprite (player)
            this.velocity = new Vector2(5, 5);


            //Here we place the loadGraphics method of each other background/sprite

            //player and other sprites .loadGraphicscontent( content )
            this.SpriteTexture = manager.Load<Texture2D>("Kame_Hame_Ha") as Texture2D;

            //Next we set the texture offset in a variable to be used in the future
            this.textureOffset.X = this.spriteTexture.Width / 12;
            this.textureOffset.Y = this.spriteTexture.Height;

            //Initialze the sprite batch object. This will be used to draw the sprite
            this.batch = new SpriteBatch( graphics.GraphicsDevice );

            //Animation counter causes the sprite to a single frame twice, to create a smoother transition
            this.animCounter = this.frames;
        }


        /// <summary>
        /// Scene update method calls its objects update method, checks for collisions and
        /// makes sure that the given updates get drawn
        /// </summary>
        /// <param name="gameTime"></param>
        /// <param name="state"></param>
        public void Update( GameTime gameTime, KeyboardState state)
        {
            //This update method calls the other objects update method to create the illusion
            //of an interacting environment

            Vector2 displacement = Vector2.Zero;
            Vector2 tempPos = this.SpritePosition;

            //Moves player-sprite left
           if( state.IsKeyDown( Keys.Left ) )
            {
                displacement.X = this.velocity.X;
                tempPos.X -= displacement.X;
            }
            
            //Moves player-sprite right
            if( state.IsKeyDown( Keys.Right ) )
            {
                displacement.X = this.velocity.X;
                tempPos.X += displacement.X;
            }
            
            //Moves player-sprite up

            if( state.IsKeyDown( Keys.Up ) )
            {
                displacement.Y = this.velocity.Y;
                tempPos.Y -= displacement.Y;
            }
            
            //Moves player-sprite down
            if( state.IsKeyDown( Keys.Down ) )
            {
                displacement.Y = this.velocity.Y;
                tempPos.Y += displacement.Y;
            }

            //Here we take all the positions of all the "actual players" and test for "out-of-bounds"
            Vector2[] importantPos = { tempPos, this.TextureOffset };

            //checks to see if the current position woulbe out of bounds;
            if( this.camera.atBounds( importantPos ) )
            {
                if ( tempPos.X + this.TextureOffset.X > this.Dimension[0] )
                {
                    //Updates the background to the displacement given by the player's velocity
                    this.background.Update(gameTime, displacement);
                }

                //Once we finished checking for out of bounds we put everything the way it was.
                //if the position is out of bounds, we take it back to where it was by subtracting the
                //displacement
                tempPos = this.SpritePosition;
            }

            //At the end, we simply set the current position to the calculated position
            this.SpritePosition = tempPos;
        }


        /// <summary>
        /// Drawing method
        /// </summary>
        /// <param name="gameTime"></param>
        public void Draw(GameTime gameTime)
        {
            this.batch.Begin(SpriteBlendMode.AlphaBlend);

            this.totalTime = gameTime.TotalGameTime.Milliseconds;


            //Draws the background jpegs in their current position, Rectangle( initial x, initial y, width, height);
            for (int i = 0; i < this.background.BackgroundNames.Length; i++)
            {
                //This loop draws the background in order
                this.batch.Draw(this.background.backTexture[i], new Rectangle( this.background.xPositions[i], 0, this.background.Dimension[0], this.background.Dimension[1]), Color.White);
            }


            //Make sure that we don't get negative values
            if (this.lastReading >= 1000 || this.lastReading > this.totalTime)
            {
                this.lastReading = 0;
            }



            //Make sure that everytime we draw, we draw the new picture at 500 milliseconds intervals
            this.currDiffenrence = this.totalTime - this.lastReading;

            //Makes sure that it displays a frame every 80 milliseconds
            if (this.currDiffenrence >= 33)
            {
                //Calculates elapsed time since last frame updated, will consider drawing a new frame
                //only if the time is greater than 80 milliseconds
                this.lastReading = this.totalTime;
                this.currDiffenrence = 0;

                if (this.animCounter > 0)
                {
                    this.animCounter--;
                }

                if (animCounter == 0)
                {
                    this.temp++;
                    this.animCounter = this.frames;
                }
            }

            //Make sure to wrap around the loop array of movements.
            if (this.temp > 11 || this.temp < 0)
            {
                this.temp = 0;
            }

            //draws the current step in the animation process
            this.batch.Draw( this.spriteTexture, new Rectangle( (int)this.SpritePosition.X, (int)this.SpritePosition.Y, this.spriteTexture.Width / 12, this.spriteTexture.Height ), new Rectangle(( this.spriteTexture.Width * this.temp) / 12, 0, this.spriteTexture.Width / 12, this.spriteTexture.Height ), Color.White );

            
            //End drawing the scene
            this.batch.End();

        }

    }
}
